﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Management;
using System.Threading;

namespace Client
{
    public partial class MainDisplay : Form
    {        
        // Function is called to force a reload of the Windows Registry
        [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
        public static extern bool SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);

        #region Variables

        NetComm.Client client;

        #endregion

        // Constructor
        public MainDisplay()
        {
            InitializeComponent();
        }
                                
        #region Form events

        // Load
        private void MainDisplay_Load(object sender, EventArgs e)
        {
            tb_nick.Text = GetVolumeID("c");
        }

        // Closing
        private void MainDisplay_FormClosing(object sender, FormClosingEventArgs e)
        {
            if ((client != null) && (client.isConnected))
            {
                // Unsubscribe
                client.Connected -= client_Connected;
                client.Disconnected -= client_Disconnected;
                client.DataReceived -= client_DataReceived;

                client.Disconnect();

                Thread.Sleep(2000);
            }
            
            e.Cancel = false;
        }

        #endregion

        #region Client functions

        // Send Command and parameters
        private void SendCmd(string from, string to, string cmd, string param)
        {
            string msg = "";
            msg += "from:" + from;
            msg += "|";
            msg += "to:" + to;
            msg += "|";
            msg += "cmd:" + cmd;
            msg += "|";
            msg += "param:" + param;

            // ha mindenkinek szól
            if (to == "broadcast")
            {                
                foreach (string id in chbl_clients.Items)
                {
                    // ha nem mi vagyunk azok
                    if (id != tb_nick.Text)
                        client.SendData(ConvertStringToBytes(msg), id);
                }
            }
            // ha célszemélynek
            else
            {
                client.SendData(ConvertStringToBytes(msg), to);
            }

        }

        // Get volume ID for identifying the client
        private string GetVolumeID(string drive)
        {
            ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""" + drive + @":""");
            dsk.Get();
            string volumeSerial = dsk["VolumeSerialNumber"].ToString();
            return volumeSerial;
        }

        #endregion

        #region Client Events

        // Connect
        void client_Connected()
        {
            Log.AppendText(DateTime.Now + " - Connected succesfully!" + Environment.NewLine);
            tssl.Text = "Connected to: " + tb_server.Text;     

            tb_nick.Enabled = false;
            tb_port.Enabled = false;
            tb_server.Enabled = false;
            chb_hide.Enabled = true;
            chb_broadcast.Enabled = true;
            panel2.Enabled = true;
        }

        // Disconnect
        void client_Disconnected()
        {
            Log.AppendText(DateTime.Now + " - Disconnected from host!" + Environment.NewLine);
            tssl.Text = "Disconnected from: " + tb_server.Text;    

            tb_nick.Enabled = true;
            tb_port.Enabled = true;
            tb_server.Enabled = true;
            chb_connect.Checked = false;

            chb_hide.Checked = false;
            chb_hide.Enabled = false;

            chb_broadcast.Checked = false;
            chb_broadcast.Enabled = false;

            panel2.Enabled = false;

            chbl_clients.Items.Clear();
        }
        
        // Data Recieved
        void client_DataReceived(byte[] Data, string ID)
        {
            #region Extract parameters from recieved data
            string d = ConvertBytesToString(Data);

            string[] lines = d.Split('|');

            string from = lines[0].Replace("from:", "");
            string to = lines[1].Replace("to:", "");
            string cmd = lines[2].Replace("cmd:", "");
            string param = lines[3].Replace("param:", "");
            #endregion

            #region Log Recieved Data to logwindow
            Log.AppendText(DateTime.Now + " - " + d + Environment.NewLine);
            #endregion

            switch (cmd)
            {
                #region Get Partnerlist
                case "addclientlist":
                    {
                        string[] clients = param.Split(',');

                        for (int i = 0; i < clients.Length; i++)
                        {
                            chbl_clients.Items.Add(clients[i]);
                        }
                    }
                    break;
                #endregion

                #region Add client to partnerlist
                case "addclient":
                    {
                        chbl_clients.Items.Add(param);
                    }
                    break;
                #endregion

                #region Delete client from partnerlist
                case "delclient":
                    {
                        if (chbl_clients.Items.Contains(param))
                            chbl_clients.Items.Remove(param);
                    }
                    break;
                #endregion                           

                #region Messages
                case "msg":
                    {
                        tb_result.AppendText(DateTime.Now + " - " + from + ": " + param + Environment.NewLine);
                    }
                    break;
                #endregion

                #region Szgpadatok
                case "info":
                    {
                        SendCmd(to, from, "msg", "Rendszernev: " + PCInfos.SystemProductName);
                        SendCmd(to, from, "msg", "BIOS gyarto: " + PCInfos.BIOSVendor);
                        SendCmd(to, from, "msg", "BIOS verzio: " + PCInfos.BIOSVersion);

                        SendCmd(to, from, "msg", "Processzor: " + PCInfos.ProcessorNameString);
                        SendCmd(to, from, "msg", "Utasitaskeszlet: " + PCInfos.Identifier);
                    }
                    break;
                #endregion

            }

        }

        #endregion                   

        #region Convert: Bytes <-> String
        string ConvertBytesToString(byte[] bytes)
        {
            return ASCIIEncoding.ASCII.GetString(bytes);
        }

        byte[] ConvertStringToBytes(string str)
        {
            return ASCIIEncoding.ASCII.GetBytes(str);
        }
        #endregion

        #region UI things
        private void tb_nick_Enter(object sender, EventArgs e)
        {
            if (tb_nick.Text == "nick")
                tb_nick.Text = "";
        }

        private void tb_server_Enter(object sender, EventArgs e)
        {
            if (tb_server.Text == "server ip")
                tb_server.Text = "";
        }

        private void tb_port_Enter(object sender, EventArgs e)
        {
            if (tb_port.Text == "port")            
                tb_port.Text = "";            
        }

        private void tb_data_Leave(object sender, EventArgs e)
        {
            if ((sender as TextBox).Text == "")
            {
                (sender as TextBox).Text = (sender as TextBox).Tag.ToString();
            }
        }
        #endregion

        //----------------------------------------------------------------------

        // Connect / Disconnect
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (chb_connect.Checked)
            {
                client = new NetComm.Client();

                client.Connected += new NetComm.Client.ConnectedEventHandler(client_Connected);
                client.Disconnected += new NetComm.Client.DisconnectedEventHandler(client_Disconnected);
                client.DataReceived += new NetComm.Client.DataReceivedEventHandler(client_DataReceived);

                if (tb_server.Text != "" && tb_port.Text != "" && tb_nick.Text != "")
                    client.Connect(tb_server.Text, Convert.ToInt32(tb_port.Text), tb_nick.Text);
                else
                    tssl.Text = "Type in Nick, Server and Port!";
            }
            else
            {
                if ((client != null) && (client.isConnected))
                    client.Disconnect();
                
                chbl_clients.Items.Clear();
            }
        }
        
        // Send Commands
        private void SendButton_Click(object sender, EventArgs e)
        {
            if (cb_cmd.Text != "")
            {
                if (chbl_clients.Items.Count > 0)
                {
                    foreach (string id in chbl_clients.CheckedItems)
                    {
                        SendCmd(tb_nick.Text, id, cb_cmd.Text, ChatMessage.Text);
                    }

                    ChatMessage.Clear();
                }
                else
                {
                    tssl.Text = "The clientlist is empty!";
                }
            }
            else
            {
                tssl.Text = "Type in or select a command!";
            }
        }

        // KeyUP = Enter
        private void ChatMessage_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                SendButton.PerformClick();
                e.Handled = true;
            }
        }

        // Hide in partnerlist
        private void hide_CheckedChanged(object sender, EventArgs e)
        {
            if (chbl_clients.Items.Count > 0)
            {
                if (chb_hide.Checked)
                {
                    SendCmd(tb_nick.Text, "broadcast", "delclient", tb_nick.Text);
                }
                else
                    SendCmd(tb_nick.Text, "broadcast", "addclient", tb_nick.Text);
            }
            else
            {
                tssl.Text = "The clientlist is empty - no partner selected...";
            }
        }

        // Broadcast checkbox
        private void chb_broadcast_CheckedChanged(object sender, EventArgs e)
        {            
            for (int i = 0; i < chbl_clients.Items.Count; i++)
                chbl_clients.SetItemChecked(i, chb_broadcast.Checked);                       
        }
       
    }
}
